###################################################################### Product:      KnowledgeEngine (Plone Edition)## File:         AssessmentExportReport.py## Copyright:    Copyright (c) 2005, Faulkner Technologies## Author:       Brian Oliver## Description:  This report exports a collection of assessments#               as XML#
# See Also:     Report, MultipleAssessmentReport#####################################################################

####################################################################### Knowledge Engine Library Importsfrom Products.KnowledgeEngine.Common import *from Products.KnowledgeEngine.Core import *from Products.KnowledgeEngine.MultipleAssessmentReport import MultipleAssessmentReport, MultipleAssessmentReportInfofrom Products.KnowledgeEngine.PropertyDefinition import *from Products.KnowledgeEngine.PropertyTypes import *from Products.KnowledgeEngine.PropertyFormats import *from Products.KnowledgeEngine.PropertyStructures import *from Products.KnowledgeEngine.EventDefinition import *
from Products.KnowledgeEngine.WizardStepDefinition import *

####################################################################### Zope Library Importsfrom Globals import DTMLFilefrom ImageFile import ImageFile

####################################################################### Python Library Imports# (none)

####################################################################### AssessmentExportReportInfo Class Definitionclass AssessmentExportReportInfo(MultipleAssessmentReportInfo):    """        Defines the class info methods, defining information about        the class without needing an instance of the class    """        #---------------------------------------------------------------#        def getClassName(self):        """            Returns the name of the class for which             we are providing information.        """        return 'AssessmentExportReport'
    #---------------------------------------------------------------#
    
    def getDisplayName(self):        """            Return a friendly name for the class instances            (this is used for displaying in lists etc)        """            return "Export Assessments Report"            #---------------------------------------------------------------#
    def getIdentityType(self):        """            Return the identity type.          """                return "AssessmentExportReport"            #---------------------------------------------------------------#        def getClassIcon(self):        """            Return the appropriate icon file for the class.        """                return ImageFile('skins/AssessmentExportReport_icon.gif', globals())        #---------------------------------------------------------------#
    
    def onConfigureProperties(self):        """            Automatically called by the Knowledge Engine once            the class has been loaded.  Use this method to register             class specific properties using the PropertyReflection interface.                        If this class is sub-classed, a call must be made to            the super-class to ensure super-class properties are            correctly registered                        NOTE: This method is called before ClassInfo.onAfterStartup()                    """
        
        #initialise the super-class properties for reflection        MultipleAssessmentReportInfo.onConfigureProperties(self)        #---------------------------------------------------------------#
    
    def onConfigureEvents(self):        """            Automatically called by the Knowledge Engine once            the class has been loaded.  Use this method to register             class specific events using the EventReflection interface.                        If this class is sub-classed, a call must be made to            the super-class to ensure super-class properties are            correctly registered                        NOTE: This method is called before ClassInfo.onAfterStartup()                    """                        #initialise the super-class events for reflection        MultipleAssessmentReportInfo.onConfigureEvents(self)
        
    #---------------------------------------------------------------#
    
####################################################################### AssessmentExportReport Class Definitionclass AssessmentExportReport(MultipleAssessmentReport):    """        A class to represent a simple report that uses the components        within the containing Model to build a report    """
    
    #---------------------------------------------------------------#
    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class    _CLASSINFO = AssessmentExportReportInfo()
    
    #---------------------------------------------------------------#
    
    def __init__(self, id, identity):        "Constructor for the object"        
        MultipleAssessmentReport.__init__(self, id, identity)            #---------------------------------------------------------------#
    
    def renderReportFor(self, genericObject, request, wizardState, assessmentFilter, **args):        """            Renders the report content for the specified generic object            and the type of report        """                #add the specified genericObject to the request        request['GENERICOBJECT'] = genericObject                #dynamically determine the report page template for the specified object        return eval("self.%s_%s(self, REQUEST=request, **args)" % (genericObject.getClassInfo().getClassName(), self.getClassInfo().getClassName()))        
    #---------------------------------------------------------------#
        
    def getWizardStepDefinitions(self, context=None):
        """
            ABSTRACT: This method is used by this class to
            determine the actual wizard step definitions
            for the wizard
            
            RETURN: [WizardStepDefinition]
        """
        
        #a function to determine if an object should be displayed in the tree 
        isDisplayableFunction = lambda genericObject: genericObject.isInstanceOf("Component") or genericObject.isInstanceOf("Model")
        
        #a function to determine if an object can be selected in the tree 
        isSelectableFunction = lambda genericObject: genericObject.isInstanceOf("Assessible") or genericObject.isContainer()
                     
        #a function to determine if an object should be expanded initially in a component tree
        isInitiallyExpandedFunction = lambda genericObject: genericObject.isInstanceOf("Model")

        wizardStep1Definition = WizardStepDefinition("Report Format", "What type of file should be generated for the report?")
        wizardStep1Definition.addPropertyDefinition(PropertyDefinition(identity="reportFormat", displayName="Report Format", description="What type of file should be generated?", propertyType=pt_STRING, propertyFormat=pf_NATIVE, hasEnumeratedValues=true, enumeratedValuesMapping=[("eXtensible Markup Language (XML)", "xml"),("Comma Separated (CSV)", "csv")], defaultValue="csv"))
                
        wizardStep2Definition = WizardStepDefinition("Components to Export", "Choose the component assessments values that you would like to appear in your report.")
        wizardStep2Definition.addPropertyDefinition(PropertyDefinition(identity="exportComponents", displayName="Assessment Components To Export", defaultValue=[], description="Please select the components for which you would like to export assessment values.", propertyType=pt_NATIVE, propertyStructure=ps_LIST, propertyFormat=pf_GENERIC_OBJECT_CHOOSER, isSelectableFunction=isSelectableFunction, isDisplayableFunction=isDisplayableFunction, isInitiallyExpandedFunction=isInitiallyExpandedFunction, containerSelectionSelectsAll=true))

        wizardStep3Definition = WizardStepDefinition("Export Options", "Choose your output options for the report.")
        wizardStep3Definition.addPropertyDefinition(PropertyDefinition(identity="outputLockStatus", displayName="Output Assessment Locked Status?", defaultValue=true, description="Should the locked status for each assessment be output?", propertyType=pt_BOOLEAN, propertyFormat=pf_CHECKBOX))
        wizardStep3Definition.addPropertyDefinition(PropertyDefinition(identity="outputPath", displayName="Output Component Contexts (paths)?", defaultValue=false, description="Should the associated parent component titles be output as part of each exported component title?", propertyType=pt_BOOLEAN, propertyFormat=pf_CHECKBOX))

        return [wizardStep1Definition, wizardStep2Definition, wizardStep3Definition]

    #---------------------------------------------------------------#

    def renderReport(self, request, wizardState, **args):
        """
            Renders the report content (called by Report.generate)
            
            NOTE: Override this method to perform specific
            report generation/rendering using the provided
            parameters
        """

        #get the assessment storage service... we'll need that to manage the assessment
        assessmentStorageService = getAssessmentStorageService(self)
        
        #get the repository the report is being opened from (may be None)
        openedFromRepositoryIdentity = wizardState.getPropertyValue("openedFromRepositoryIdentity")

        #get the current user that is rendering the report
        user = request["USER"]
    
        #get the session from the request
        session = request["SESSION"]

        #get the response from the request (weird I know, but that's where it lives in Zope)
        response = request["RESPONSE"]

        #order the components as they appear in the model
        components = wizardState.getPropertyValue("exportComponents")
        components = [genericObject.getIdentity() for genericObject in self.getModel().getDescendantsByOrder() if genericObject.getIdentity() in components]
        
        #remove container components
        components = [component for component in components if not self.getModel().getComponent(component).isContainer()]
        
        wizardState.setPropertyValue("exportComponents", components)

        #get the assessment filter to use to filter out assessments from the session 
        #(this is typically set by the assessment explorer)
        assessmentFilter = wizardState.getPropertyValue("assessmentFilter")
        
        #fetch the assessments
        assessments = assessmentStorageService.getAssessmentsSatisfyingFilter(assessmentFilter, user, sortBy="dateCreated")
        request.set('ASSESSMENTS', assessments)
        
        #generate XML report?
        if wizardState.getPropertyValue('reportFormat') == 'xml':
            #set that we are exporting an xml file and that it should be downloaded
            response.setHeader("content-type", "text/xml")
            response.addHeader("content-disposition", "attachment;filename=Assessments.xml")

            #now render the report
            return eval("self.AssessmentExportReport_xml_report(self, REQUEST=request, **args)")

        #generate CSV report!
        else:
            #set that we are exporting an xml file and that it should be downloaded
            response.setHeader("content-type", "text/csv")
            response.addHeader("content-disposition", "attachment;filename=Assessments.csv")

            #now render the report
            return eval("self.AssessmentExportReport_csv_report()")
        
    #---------------------------------------------------------------#

####################################################################### Class Initialisation
# Register Class Information with the Knowledge EngineregisterGenericObjectClass(AssessmentExportReport)
#####################################################################
